/*
 *
 *  Copyright (C) 2010 Tal Eisenberg
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package tal.drivechain.gui;

import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridBagLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import tal.drivechain.chain.ChainNode;
import tal.drivechain.plugin.Module;

/**
 * A default gui module that minimizes some of the actions necessary
 * for gui modules. Requires color, windowId and layout properties defined in the modules xml.
 *
 * path: /tal.drivechain.gui/guimodule.xml:GUIModule
 * @author Main
 */
public abstract class GUIModule extends Module {
    protected Container container, noneContainer = new JPanel(new GridBagLayout());
    protected String containerId;
    protected JComponent component;
    protected dcLayout layout;
    protected GridBagLayout layoutManager;
    protected Color color = Color.white, darker = Color.white.darker();
    protected Font font = new Font("Sans Serif", Font.PLAIN, 12);
    protected boolean enabled, negative;
    private boolean visible;

    public String getContainer() { return containerId; }
    public Color getColor() { return color; }
    public Font getFont() { return font; }
    public dcLayout getLayout() { return layout; }
    public boolean getEnabled() { return enabled; }
    public boolean getNegative() { return negative; }
    public boolean getVisible() { return visible; }

    public void setContainer(String value) {
        boolean reopen = false;
        if (this.isRunning()) {
            this.stop();
            if (container!=null) {
                container.remove(component);
                relayout();
            }
            reopen = true;
        }
        String oldContainerId = containerId;
        
        containerId = value;
        if (containerId==null && getParentChain()!=null) {
            // look for a gui.Window module in the parent chain and if there's only 1 use it as a container
            GUIContainer containerMod = null;
            boolean moreThanOneContainer = false;
            for (ChainNode n : getParentChain().getChildNodes().values()) {

                if (n instanceof GUIContainer && n!=this) {
                    if (containerMod==null)
                        containerMod = (GUIContainer)n;
                    else {
                        moreThanOneContainer = true;
                        break;
                    }
                }
            }

            if (containerMod!=null && !moreThanOneContainer) {
                containerId = containerMod.getId();
            }
        }

        if (containerId == null) containerId = "none";

        if (reopen) {
            try {
                this.start();
                relayout();
            } catch (Exception e) {
                containerId = oldContainerId;
                throw new IllegalArgumentException(e.getMessage());
            }
        }
    }

    public void setVisible(Boolean value) {
        this.visible = value;
        if (component!=null)
            component.setVisible(visible);
        relayout();
    }
    public void setEnabled(Boolean value) {
        enabled = value;
    }

    public void setNegative(Boolean value) {
        negative = value;
    }
    public void setColor(Color value) {
        color = value;
        darker = color.darker();
    }
    
    public void setFont(Font value) {
        font = value;
    }
    
    public void setLayout(dcLayout value) {
        boolean reopen = false;
        if (this.isRunning()) {
            this.stop();
            reopen = true;
        }
        layout = value;
        if (reopen) this.start();
    }

    @Override
    public void start() {
        super.start();
        component.setVisible(visible);
        if (containerId.equals("none"))
            container = noneContainer;
        else container = (Container)getParentChain().findSharedObject(containerId);
        if (container==null) {
            throw new IllegalArgumentException("A container with the id of " + containerId + " does not exist.");
        } else if (!(container.getLayout() instanceof GridBagLayout)) {
            throw new IllegalArgumentException("Container " + containerId + " must have a GridBag layout manager.");
        } else {
            layoutManager = (GridBagLayout)container.getLayout();
            addComponent();           
        }
    }

    @Override
    public void stop() {
        if (container!=null && component!=null) {
            component.setVisible(false);
            container.remove(component);
            relayout();
        }
    }
    
    protected void addComponent() {
        component.setName(nodeName);
        layoutManager.setConstraints(component, layout);
        container.add(component);
    }

    protected void relayout() {
        if (container == null) return;
        Container parent = container;
        if (parent==null) return;
        Container lastParent;
        do {
            lastParent = parent;
            parent = parent.getParent();
        } while (parent!=null);
        lastParent.validate();
        if (lastParent instanceof JFrame) ((JFrame)lastParent).pack();
    }
}
